package com.cctc.juc.demo.Bitc.Fjuctools.BCountDownLatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchDemo {

    /**
     * 线程间通信方式之使用 CountDownLatch 倒数闩 / 闭锁：主线程需要自我阻塞，等到所有的任务线程都执行完成之后，才能继续执行后续的操作。
     * CountDownLatch [倒数闩 / 闭锁] 是一个常用的线程同步工具，其功能相当于一个多线程环境下的计数器，能够实现线程自我阻塞，直到指定数量的子任务线程都执行完成之后被唤醒，才能继续执行后续的操作。
     * 核心方法：
     * - public CountDownLatch(int count);
     * - public void await() throws InterruptedException;
     * - public boolean await(long timeout, TimeUnit unit) throws InterruptedException;
     * - public void countDown();
     * 使用步骤：
     * 1）调用构造器，创建倒锁，指定 CountDownLatch 的计数器，比如 100;
     * 2）主线程调用 CountDownLatch.await() 方法，进行自我阻塞，等待计数器的值变为 0（所有子任务线程全部执行完成）时被唤醒，继续执行后续的操作。
     * 3）每当一个任务线程执行完成后，调用 CountDownLatch.countDown() 方法，将计数器的值减 1。
     * CountDownLatch 与 Semaphone 的区别：
     * CountDownLatch 主要用于控制并发子任务的总线程数量；而 Semaphone 用于控制同一时刻并发任务的线程数量；二者通常结合使用，实现高并发环境下的线程同步操作。
     */

    private static class Person implements Runnable {
        private final CountDownLatch countDownLatch;
        private final int index;

        public Person(CountDownLatch countDownLatch, int index) {
            this.countDownLatch = countDownLatch;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                System.out.println("第 " + index + " 个人已到！！！");
                // 当前线程执行完成，将计数器的值减 1。
                countDownLatch.countDown();
            } catch (Exception e) {
            }
        }
    }

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Person(countDownLatch, i));
        }
        try {
            // 自我等待，等待计数器的值变为 0（所有子任务线程全部执行完成）时被唤醒，继续执行后续的操作。
            countDownLatch.await();
            System.out.println("人已到齐，开车！！！");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            executorService.shutdownNow();
        }
    }

}
